package com.fwj.common.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.fwj.common.api.AttachmentService;
import com.fwj.common.constant.FileConstant;
import com.fwj.common.dao.AttachmentMapper;
import com.fwj.common.entity.Attachment;
import com.fwj.common.model.AttachInfoVo;
import com.fwj.core.common.common.CommonUtils;
import com.fwj.core.common.common.MD5Utils;
import com.fwj.core.common.common.OSSFileUtils;
import com.fwj.core.common.common.StringGeneratorUtil;
import com.fwj.core.common.execption.CommonException;
import com.fwj.core.common.model.ResponseDTO;
import com.fwj.core.common.model.ResponseEnum;
import com.fwj.user.entity.user.UserBaseInfo;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;

/**
 * @Author: fwj
 * @Data: 2022/4/15 15:10
 * @Version 1.0
 * @Description:
 */

@Service
public class AttachmentServiceImpl implements AttachmentService {

    //添加日志工厂
    private static final Logger LOGGER = LoggerFactory.getLogger(AttachmentServiceImpl.class);

    @Autowired
    private AttachmentMapper attachmentMapper;

    @Autowired
    private SqlSessionFactory sqlSessionFactory;

    @Override
    @Transactional
    public ResponseDTO upload(MultipartFile[] files, Attachment attachment, UserBaseInfo userBaseInfo) {
        ResponseDTO responseDTO = new ResponseDTO();
        try {
            //上传文件
            List<Attachment> attachmentList = uploadAttachment(files);
            //存储基础文件信息
            List<AttachInfoVo> retAttachVoList = saveAttachInfo(attachmentList,files, attachment,userBaseInfo);
            return new ResponseDTO().success().setData(retAttachVoList);
        } catch (IOException e){
            LOGGER.error(e.toString());
            return responseDTO.fail(ResponseEnum.SERVER_ERROR);
        }
    }

    private List<AttachInfoVo> saveAttachInfo(List<Attachment> attachmentList, MultipartFile[] files, Attachment attach, UserBaseInfo userBaseInfo) {
        //保存数据到attach_info表
        int length = attachmentList.size();
        SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH,false);
        AttachmentMapper attachmentMapper = sqlSession.getMapper(AttachmentMapper.class);
        Timestamp timestamp = new Timestamp(System.currentTimeMillis());
        try {
            //批处理
            for (int i = 0; i < length; i++){
                Attachment attachment = attachmentList.get(i);
                attachment.setAttachName(files[i].getOriginalFilename());
                attachment.setFileSize(files[i].getSize() / 1024);
                attachment.setScope(attach.getScope());
                attachment.setDescription(attach.getDescription());
                attachment.setCreateTime(timestamp);
                attachment.setUpdateTime(timestamp);
                attachment.setCreator(userBaseInfo.getNumber());
                attachment.setAttachNo(MD5Utils.getMd5(StringGeneratorUtil.randomSequence(16) + MD5Utils.MD5SALT));
                attachment.setStatus(FileConstant.NORMAL);
                attachment.setIsSecure(attach.getIsSecure());
                attachmentMapper.insertSelective(attachment);
                //每执行1000条提交并清空缓存
                if (( i & 1000) == 999){
                    sqlSession.commit();
                    sqlSession.clearCache();
                }
            }
            //最后一次提交剩余的
            sqlSession.commit();
            sqlSession.clearCache();
            List<AttachInfoVo> attachInfoVoList = buildAttachVoList(attachmentList);
            return attachInfoVoList;
        } catch (Exception e){
            LOGGER.error(e.toString());
            throw new CommonException(ResponseEnum.SERVER_ERROR);
        } finally {
            if (null != sqlSession){
                sqlSession.close();
            }
        }
    }

    private List<AttachInfoVo> buildAttachVoList(List<Attachment> attachmentList) {
        List<AttachInfoVo> attachInfoVoList = JSONObject.parseArray(JSONArray.parseArray(JSON.toJSONString(attachmentList)).toJSONString(),AttachInfoVo.class);
        int length = attachInfoVoList.size();
        for (int i = 0; i < length; i++){
            AttachInfoVo attachInfoVo = attachInfoVoList.get(i);
            if (CommonUtils.isEmpty(attachInfoVo.getIsSecure())){ attachInfoVo.setIsSecure("NO"); }
            if (CommonUtils.isEmpty(attachInfoVo.getScope())) { attachInfoVo.setScope("ALL"); }
        }
        return attachInfoVoList;
    }

    private List<Attachment> uploadAttachment(MultipartFile[] files) throws IOException {
        List<Attachment> attachmentList = new ArrayList<>();
        //获取文件数量
        for (MultipartFile file : files){
            //获取文件信息
            InputStream inputStream = file.getInputStream();
            String fileName = file.getOriginalFilename();
            //上传文件到阿里云
            String uploadPath = OSSFileUtils.upload(fileName,inputStream);
            //如果路径为空，则上传失败
            if (CommonUtils.isEmpty(uploadPath)){
                throw new CommonException(ResponseEnum.FILE_MISS);
            }
            //存入文件信息到List
            Attachment attachment = new Attachment();
            attachment.setLocation(uploadPath);
            attachment.setType(file.getContentType());
            attachmentList.add(attachment);
        }
        return attachmentList;
    }

    @Override
    public ResponseDTO download(JSONObject jsonObject, HttpServletRequest request, HttpServletResponse response) {
        ResponseDTO responseDTO = new ResponseDTO();
        try {
            String attachNo = jsonObject.getString("attachNo");
            Attachment attachment = getAttach(attachNo);
            if (CommonUtils.isEmpty(attachment)){ throw new CommonException(ResponseEnum.FILE_NOT_EXISTS); }
            OSSFileUtils.download(attachment.getLocation(),request,response);
            return responseDTO.success();
        } catch (Exception e){
            return responseDTO.fail();
        }
    }

    private Attachment getAttach(String attachNo) throws Exception{
        Attachment reqAttach = new Attachment();
        reqAttach.setAttachNo(attachNo);
        reqAttach.setIsSecure("NO");
        reqAttach.setStatus(FileConstant.NORMAL);
        return attachmentMapper.selectOne(reqAttach);
    }

    @Override
    @Transactional
    public ResponseDTO delete(JSONObject jsonObject) {
        try {
            String attachNo = jsonObject.getString("attachNo");
            Attachment attachment = new Attachment();
            attachment.setAttachNo(attachNo);
            attachment.setStatus(FileConstant.NORMAL);
            Attachment delAttach = attachmentMapper.selectOne(attachment);
            if (CommonUtils.isEmpty(delAttach)){ throw new CommonException(ResponseEnum.FILE_NOT_EXISTS); }
            delAttach.setStatus(FileConstant.FALSE_DELETED);
            attachmentMapper.updateByPrimaryKeySelective(delAttach);
            return new ResponseDTO().success();
        } catch (Exception e){
            return new ResponseDTO().fail();
        }
    }

    @Override
    public ResponseDTO realDelete(List<String> keys) {
        //先删除阿里云文件
        OSSFileUtils.delete(keys);
        //更新数据库文件
        //刷新数据到attach_info表
        int length = keys.size();
        SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH,false);
        AttachmentMapper attachmentMapper = sqlSession.getMapper(AttachmentMapper.class);
        Timestamp timestamp = new Timestamp(System.currentTimeMillis());
        try {
            //批处理
            for (int i = 0; i < length; i++){
                attachmentMapper.updateAttachmentByAttachNo(keys.get(i),timestamp,FileConstant.DELETED);
                //每执行1000条提交并清空缓存
                if (( i & 1000) == 999){
                    sqlSession.commit();
                    sqlSession.clearCache();
                }
            }
            //最后一次提交剩余的
            sqlSession.commit();
            sqlSession.clearCache();
            return new ResponseDTO().success();
        } catch (Exception e){
            LOGGER.error(e.toString());
            throw new CommonException(ResponseEnum.SERVER_ERROR);
        } finally {
            if (null != sqlSession){
                sqlSession.close();
            }
        }
    }


}
